#include "stdafx.h"
#include "Device.h"
#include "ColorDef.h"

int Device::SectionWidth_ = 2;
int Device::InsuHeight_   = 6;

Device::Device(void)
	: bSealed_(false)
	, connectFlag_(-1)
	, bFirstCreate_(false)
{
}


Device::Device(CWnd* pParent)
	: Graphic(pParent)
	, bSealed_(false)
	, connectFlag_(-1)
	, name_(pParent)
	, bFirstCreate_(true)
{
	devData_.bValid_    = true;
	devData_.stationID_ = 0;
	devData_.addr_      = 0XFFFF;
	devData_.btnID_     = 0XFFFF;
	devData_.byteFlag_  = 0XFFFF;
	devData_.bitFlag_   = 0XFFFF;
	devData_.dir_       = DIR_UP;
	devData_.boardID_   = 0XFFFF;
	devData_.startRow_  = 0XFFFF;
}


Device::~Device(void)
{
}


IMPLEMENT_SERIAL(Device, Graphic, 1)


void Device::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{	// storing code
		ar.Write(&devData_, sizeof(devData_));
	}
	else
	{	// loading code
		ar.Read(&devData_, sizeof(devData_));
	}

	name_.Serialize(ar);
}



void Device::drawSection(CPaintDC& dc, CPoint pt[], int nPt)
{
	dc.SelectObject(SectionPen());
	dc.MoveTo(pt[0]);
	for (int i = 1; i < nPt; i++)
		dc.LineTo(pt[i]);
}


void Device::drawSealFrame(CPaintDC& dc, CPoint pt[], int nPt)
{
	if (bSealed_)
	{
		dc.SelectObject(RedPen());
		dc.MoveTo(pt[0]);
		for (int i = 1; i < nPt; i++)
			dc.LineTo(pt[i]);
		dc.LineTo(pt[0]);
	}
}


CPoint Device::getCrossPoint(CPoint& line1Pt1, CPoint& line1Pt2, CPoint& line2Pt1, CPoint& line2Pt2)
{
	double a1 = (double)(line1Pt2.y - line1Pt1.y) / (double)(line1Pt2.x - line1Pt1.x);
	double b1 = line1Pt1.y - a1 * (double)line1Pt1.x;

	double a2 = (double)(line2Pt2.y - line2Pt1.y) / (double)(line2Pt2.x - line2Pt1.x);
	double b2 = line2Pt1.y - a2 * (double)line2Pt1.x;

	double x = (b2 - b1) / (a1 - a2);
	double y = a1 * x + b1;

	return CPoint((int)x, (int)y);
}



void Device::drawInsu(CPaintDC& dc, CPoint pt[], int type[], int nInsu)
{
	dc.SelectObject(SectionPen());

	for (int i = 0; i < nInsu; i++)
	{
		CPoint* pPt[2] = { pt + 2 * i, pt + 2 * i + 1 };
		if (type[i] == NORMAL_INSU)
		{
			dc.MoveTo(*pPt[0]);
			dc.LineTo(*pPt[1]);
		}
		else if (type[i] == LIMIT_INSU)
		{
			CPoint center((pPt[0]->x + pPt[1]->x) / 2, (pPt[0]->y + pPt[1]->y) / 2);
			int r = InsuHeight_ / 2;
			CRect circleRect(center, center);
			circleRect.InflateRect(r, r);
			dc.Ellipse(circleRect);
		}
	}
}

BEGIN_MESSAGE_MAP(Device, Graphic)
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSELEAVE()
	ON_WM_WINDOWPOSCHANGED()
END_MESSAGE_MAP()


void Device::OnMouseMove(UINT nFlags, CPoint point)
{
	TRACKMOUSEEVENT time;       
	time.cbSize      = sizeof(TRACKMOUSEEVENT);
	time.dwFlags     = TME_HOVER | TME_LEAVE;
	time.dwHoverTime = HOVER_DEFAULT;
	time.hwndTrack   = m_hWnd;
	_TrackMouseEvent(&time);

	bSealed_ = true;
	Invalidate();

	Graphic::OnMouseMove(nFlags, point);
}


void Device::OnMouseLeave()
{
	bSealed_ = false;
	Invalidate();

	Graphic::OnMouseLeave();
}


CPoint Device::getNameTopLeft(const CPoint& pt1, const CPoint& pt2)
{
	CClientDC dc(this);
	dc.SelectObject(&name_.font_);
	CSize textSz = dc.GetTextExtent(name_.text_);

	CPoint midPt((pt1.x + pt2.x)/2, (pt1.y + pt2.y)/2);
	midPt.Offset(-textSz.cx/2, textSz.cy/2);

	return midPt;
}


void Device::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
	Graphic::OnWindowPosChanged(lpwndpos);

	if (name_.GetSafeHwnd() == NULL)
	{
		name_.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, CRect(), GetParent(), 0);
	}

	setNamePos();
}


CRect Device::getDevRect(CPoint pt[], int nPt)
{
	CPoint topLeft     = pt[0];
	CPoint rightBottom = pt[0];

	for (int i = 1; i < nPt; i++)
	{
		topLeft.x = min(topLeft.x, pt[i].x);
		topLeft.y = min(topLeft.y, pt[i].y);
		rightBottom.x = max(rightBottom.x, pt[i].x);
		rightBottom.y = max(rightBottom.y, pt[i].y);
	}

	CRect rect(topLeft, rightBottom);
	rect.InflateRect(10, 10);

	return rect;
}
